<?php

namespace app\service;

use support\Model;
use teamones\filter\Enforcer;
use think\Paginator;
use think\db\exception\DbException;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

abstract class BaseService
{
    protected Model $model;

    abstract public function getModel(): Model;

    public array $allowUpdateFields = [];

    protected array $with = [];

    /**
     * @param array $all
     * @return Model|\think\Model
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function create(array $all)
    {
        $model = $this->getModel()::create($all['data']);
        return $model->with($this->with)->find($model->id);
    }

    /**
     * 删除
     * @param array $all
     * @return bool
     */
    public function delete(array $all)
    {
        return $this->getModel()::destroy($all['data']['ids']);
    }

    /**
     * 查询
     * @param array $param
     * @return LengthAwarePaginator|Paginator
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function select(array $param)
    {
        Paginator::currentPageResolver(function () {
            return request()->all()['param']['page'][0] ?? 1;
        });
        $query = $this->getModel();
        if (!empty($this->with)) {
            $query = $query->with($this->with);
        }
        if (!empty($param['param']['filter'])) {
            $where = Enforcer::parseWhere($param['param']['filter']);
            $query = $query->where($where);
        }
        if (!empty($param['param']['order'])) {
            $query = $query->order($param['param']['order']);
        }
        if (!empty(request()->all()['param']['page'])) {
            return $query->paginate($param['param']['page'][1]);
        } else {
            return $query->paginate(config('app.paginate_default_page_size'));
        }
    }

    /**
     * @param array $all
     * @return Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function update(array $all)
    {
        $category = $this->getModel()::find($all['data']['id']);
        $category->allowField($this->allowUpdateFields)->save($all['data']);
        return $category;
    }

    /**
     * 查询单条数据通用逻辑
     * @param $id
     * @return array|Model|\think\Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function find($id)
    {
        $model = $this->getModel();

        if (!empty($this->with)) {
            $model = $model->with($this->with);
        }
        return $model->find($id);
    }
}
